﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Viper
{
    public class Assembly
    {
        public List<vClass> Classes = new List<vClass>();
        public List<string> DLLs = new List<string>();
        public int Entrypoint = 0;
        public void addClass(vClass Class)
        {
            Classes.Add(Class);
        }
        public void InvokeMethod(string name)
        {
        }
        public void LoadGEX(string path)
        {
            GEX excutable = GEX.LoadFromFile(path);
            Buffer data = new Buffer(0);
            Entrypoint = excutable.CodeStart;
           // System.Environment.CurrentDirectory = System.IO.Path.GetDirectoryName(path);
            foreach (string s in excutable.DLLs)
            {
                LoadGEX(s); // Dynamically Link all GEX files during runtime
                
            }
            foreach (GEXResource gr in excutable.Files)
            {
                data.buffer = gr.Data;
                // Skip magic number (vClass)
                data.pos = 6;
                int length = 0;
                
                
            
                vClass CLASS = new vClass(gr.Name.Replace(".bytecode", ""));
                data.ReadString();
                length = (byte)data.Read();
                for (int i = 0; i < length; i++)
                {
                    Console.WriteLine("lol");
                    CLASS.Fields.Add(data.ReadString());
                }
                data.ReadString(); // Begin reading the .text section , this contains the executable code
                length = data.ReadInt32();
                if (length != 0)
                {

                    for (int i = 0; i < length; i++)
                    {
                        
                           CLASS.Code.Write((uint)i, data.Read());
                           CLASS.pos = (uint)i;
                        
                    }
                }
                data.ReadString(); // Begin reading .meta section , this contains all symbols (Required for dynamic linking)
                length = data.ReadInt32();
                for (int i = 0; i < length; i++)
                {
                
                    CLASS.MetaData += ((char)data.Read()).ToString();
                }
                CLASS.End(); CLASS.ReadMetaData(); // Gets all method names , this is required for static linking.
                
                this.addClass(CLASS);
            }
        }
        public void CreateGEX(string path)
        {
            GEX executable = new GEX(path);
            executable.ApplicationAuthor = "Noname";
            executable.ApplicationName = "My Program";
            executable.CodeStart = Entrypoint;
            executable.Checksum = "";
            executable.Version = 1;
            executable.CreatorUsername = "d";
            executable.DLLs = DLLs;
            executable.DefaultPackage = "program.bytecode";
            foreach (vClass Class in Classes)
            {
                GEXResource gr = new GEXResource();
                gr.Name = Class.Name + ".bytecode";
                List<Byte> Data = new List<byte>();
                if (Class.isMainClass)
                {
                    executable.DefaultPackage = Class.Name + ".bytecode";
                }
                foreach (char b in "vClass")
                {
                    Data.Add((byte)b);
                }
                Data.Add((byte)(".fields").Length); 
                
                foreach (char b in (".fields"))
                {
                    Data.Add((byte)b);
                }
                Data.Add((byte)Class.Fields.Count);
                foreach (string str in Class.Fields)
                {
                    Console.WriteLine("wait wut?");
                    Console.ReadLine();
                    Data.Add((byte)str.Length);
                    foreach (byte b in str)
                    {
                        Data.Add(b);
                    }
                }
                Data.Add((byte)".text".Length);
                foreach (char b in ".text")
                {
                    Data.Add((byte)b);
                }
                foreach (Byte b in BitConverter.GetBytes(Class.generateByteCode().Length))
                {
                    
                    Data.Add(b);
                }
                foreach (Byte b in Class.generateByteCode())
                {
                    Data.Add(b);
                }
                Data.Add((byte)".meta".Length);
                foreach (char b in ".meta")
                {
                    Data.Add((byte)b);
                }
                foreach (Byte b in BitConverter.GetBytes(Class.MetaData.Length))
                {
                    Data.Add(b);
                }
                foreach (char b in Class.MetaData)
                {
                    Data.Add((byte)b);
                }
                gr.Data = Data.ToArray();
                
                executable.Files.Add(gr);
            }
            executable.Save();
        }
    }
}
